#pragma once

#include <stdexcept>
#include <cmath>

namespace BR {

template<class Tp>
struct Vector2D
{
	Tp i, j;

	static const Vector2D<Tp>  ZERO;

	Vector2D(Tp				const	& = Tp(), Tp const & = Tp()	);
	Vector2D(Vector2D<Tp>	const	&  							);


	Vector2D<Tp>& operator= (const Vector2D<Tp>&);
	Vector2D<Tp>  operator+ (const Vector2D<Tp>&) const;
	Vector2D<Tp>  operator- (const Vector2D<Tp>&) const;
	Vector2D<Tp>  operator* (const Tp&          ) const;
	Vector2D<Tp>  operator/ (const Tp&          ) const;
	Vector2D<Tp>& operator+=(const Vector2D<Tp>&);
	Vector2D<Tp>& operator-=(const Vector2D<Tp>&);
	Vector2D<Tp>& operator*=(const Tp&          );
	Vector2D<Tp>& operator/=(const Tp&          );
	Vector2D<Tp>  operator+ (void               ) const;
	Vector2D<Tp>  operator- (void               ) const;
	const Tp&    operator[](size_t             ) const;
		Tp&    operator[](size_t             );
	Tp            Dot(const Vector2D<Tp>&) const;
	Tp            Cross(const Vector2D<Tp>&) const;
	Tp            Norm() const;
	Tp            NormSqr() const;
	Vector2D<Tp>& Unitize();
	Vector2D<Tp>  Unit() const;
	Tp            Arg() const;
	Tp            TanArg() const;
	Vector2D<Tp>& Rotate(const Tp&);
	Vector2D<Tp>& Rotate(const Tp&, const Tp&);
};

/*
 *  helper function
 */
template<class Tp>
Vector2D<Tp> Rotate(const Vector2D<Tp>&, const Tp&);

template<class Tp>
Vector2D<Tp> Rotate(const Vector2D<Tp>&, const Tp&, const Tp&);

template<class Tp>
inline Vector2D<Tp> operator*(const Tp&, const Vector2D<Tp>&);

template<class Tp>
inline Tp Angle(const Vector2D<Tp>&, const Vector2D<Tp>&);

template<class Tp>
inline Tp CosAngle(const Vector2D<Tp>&, const Vector2D<Tp>&);

}
